<template>
  <div class="danmaku-container">
    <!-- 视频播放器 -->
    <video
        ref="videoPlayer"
        :src="currentVideo"
        @timeupdate="handleTimeUpdate"
        @ended="handleVideoEnd"
        controls
        width="800"
    ></video>

    <!-- 弹幕画布 -->
    <div class="danmaku-canvas" ref="danmakuCanvas">
      <div
          v-for="danmaku in visibleDanmaku"
          :key="danmaku.id"
          class="danmaku-item"

          :style="getDanmakuStyle(danmaku)"
          @click="handleLike(danmaku)"
          @animationend="removeDanmaku(danmaku)"
      >
        <span v-if="danmaku.likeCount > 0" class="like-icon">❤️</span>
        <span :class="['content', { 'mine': danmaku.isMine }]">
          {{ danmaku.content }}
        </span>
        <span class="like-count" v-if="danmaku.likeCount > 0">
          {{ danmaku.likeCount }}
        </span>
      </div>
    </div>

    <!-- 弹幕发送控件 -->
    <div class="danmaku-control">
      <input v-model="newDanmaku.content" placeholder="输入弹幕内容">
      <select v-model="newDanmaku.color">
        <option value="#000000">黑色</option>
        <option value="#ff0000">红色</option>
        <option value="#00ff00">绿色</option>
      </select>
      <select v-model="newDanmaku.position">
        <option value="top">顶部</option>
        <option value="center">居中</option>
        <option value="bottom">底部</option>
      </select>
      <button @click="sendDanmaku">发送</button>
    </div>
    <div class="test-box"></div>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'

const props = defineProps({
  videoList: {
    type: Array,
    default: () => []
  },
  currentUser: {
    type: Number,
    required: true
  },
  moveDuration: {
    type: Number,
    default: 5 // 默认10秒完成移动
  },
  loop: {
    type: Boolean,
    default: true
  }
})


// ========== 响应式数据 ========== //
const videoPlayer = ref(null)          // 视频DOM引用
const currentVideoIndex = ref(0)       // 当前播放视频索引
const visibleDanmaku = ref([])         // 当前可见弹幕列表
const lastFetchTime = ref(0)           // 上次获取弹幕的时间点
// 新增弹幕容器尺寸跟踪
const danmakuCanvas = ref(null)
const canvasWidth = ref(0)

// 弹幕缓存结构：Map<videoId, Map<起始时间秒数, 弹幕数组>>
const danmakuCache = reactive(new Map())
const newDanmaku = reactive({
  content: '',
  color: '#000000',
  position: 'top',
  size: 24
})
// 监听容器尺寸变化
onMounted(() => {
  const resizeObserver = new ResizeObserver(entries => {
    canvasWidth.value = entries[0].contentRect.width
  })
  resizeObserver.observe(danmakuCanvas.value)
})
// ========== WebSocket模拟 ========== //
// 实际使用时需替换为 new WebSocket('wss://your-url')
const ws = ref({
  send: data => {
    // 模拟发送逻辑：直接处理为接收新弹幕
    const danmaku = JSON.parse(data)
    handleNewDanmaku(danmaku)
  },
  onmessage: null
})

// ========== 计算属性 ========== //
// 当前视频URL
const currentVideo = computed(() =>
    props.videoList[currentVideoIndex.value]?.url || ''
)
// 当前视频ID
const currentVideoId = computed(() =>
    props.videoList[currentVideoIndex.value]?.id || null
)

// ========== 生命周期 ========== //
onMounted(() => {
  // 监听视频seek事件（拖动进度条）
  // videoPlayer.value.addEventListener('seeked', handleSeek)
  initDanmakuAnimation()
})

onUnmounted(() => {
  // 移除事件监听
  // videoPlayer.value.removeEventListener('seeked', handleSeek)
  cancelAnimationFrame(animationFrame.value)
})


// ========== 新增动画相关逻辑 ========== //
const animationFrame = ref(null)
const startTimestamp = ref(0)
const currentProgress = ref(0)

/**
 * 更新可见弹幕（核心过滤逻辑）
 * @param {number} currentTime - 当前播放时间（秒）
 */
const updateVisibleDanmaku = (currentTime) => {
  // 1. 定义时间窗口范围（前30秒至后30秒）
  const timeWindowStart = currentTime - 30
  const timeWindowEnd = currentTime + 30

  // 2. 过滤出在时间窗口内的弹幕
  const inWindowDanmaku = visibleDanmaku.value.filter(d =>
      d.playTime >= timeWindowStart &&
      d.playTime <= timeWindowEnd
  )

  // 3. 获取需要新增的缓存弹幕（避免重复添加）
  const cached = getCachedDanmaku(timeWindowStart, timeWindowEnd)
  const newDanmaku = cached.filter(c =>
      !inWindowDanmaku.some(d => d.id === c.id)
  )

  // 4. 更新可见弹幕列表
  visibleDanmaku.value = [...inWindowDanmaku, ...newDanmaku]

  // 5. 清理超出时间窗口的弹幕（性能优化）
  visibleDanmaku.value = visibleDanmaku.value.filter(d =>
      d.playTime >= timeWindowStart - props.moveDuration && // 保留即将进入的弹幕
      d.playTime <= timeWindowEnd + props.moveDuration      // 保留刚刚离开的弹幕
  )
}

// 修改后的动画更新方法
// 修改后的弹幕进度更新方法
const updateDanmakuPosition = () => {
  const videoCurrentTime = videoPlayer.value?.currentTime || 0

  // 创建新数组触发响应式更新
  visibleDanmaku.value = visibleDanmaku.value.map(danmaku => {
    // 计算存活时间
    const aliveTime = videoCurrentTime - danmaku.playTime

    // 计算新进度（保留两位小数减少渲染压力）
    const progress = parseFloat(
        Math.min(Math.max(aliveTime / props.moveDuration, 0), 1)
    ).toFixed(2)

    // 返回新对象触发响应式更新
    return {
      ...danmaku,
      progress,
      // 添加位移计算缓存（像素单位）
      translateX: canvasWidth.value * (1 - progress)
    }
  })

  // 过滤已完成动画的弹幕（progress > 1）
  visibleDanmaku.value = visibleDanmaku.value.filter(d => d.progress <= 1.1)

  animationFrame.value = requestAnimationFrame(updateDanmakuPosition)
}
// /**
//  * 更新弹幕位置
//  */
// const updateDanmakuPosition = () => {
//   // 1. 获取视频当前播放时间
//   const videoCurrentTime = videoPlayer.value?.currentTime || 0
//
//   // 2. 过滤需要显示的弹幕（在播放时间±30秒范围内）
//   const validDanmaku = visibleDanmaku.value.filter(d =>
//       d.playTime >= videoCurrentTime - 30 &&
//       d.playTime <= videoCurrentTime + 30
//   )
//
//   // 3. 计算每个弹幕的动画进度
//   validDanmaku.forEach(danmaku => {
//     // 计算弹幕存活时间（当前时间 - 弹幕出现时间）
//     const aliveTime = videoCurrentTime - danmaku.playTime
//
//     // 计算动画进度百分比（0~1）
//     const progress = Math.min(aliveTime / props.moveDuration, 1)
//
//
//     // console.log(danmaku.progress)
//     // 更新弹幕位置
//     danmaku.progress = progress
//
//     // 自动移除已经移出屏幕的弹幕
//     if (progress >= 1) {
//       visibleDanmaku.value = visibleDanmaku.value.filter(d => d.id !== danmaku.id)
//     }
//   })
//
//   // 4. 循环更新
//   animationFrame.value = requestAnimationFrame(updateDanmakuPosition)
// }

/**
 * 初始化弹幕动画
 */
const initDanmakuAnimation = () => {
  cancelAnimationFrame(animationFrame.value)
  startTimestamp.value = performance.now()
  updateDanmakuPosition()
}




// ========== 核心方法 ========== //
/**
 * 处理视频时间更新事件
 * 每25秒触发一次弹幕加载
 */
const handleTimeUpdate = () => {
  const currentTime = videoPlayer.value.currentTime
  // 时间间隔检查（减少频繁请求）
  if (currentTime - lastFetchTime.value > 25) {
    loadDanmaku(currentTime)
    lastFetchTime.value = currentTime
  }
  updateVisibleDanmaku(currentTime)
  // updateDanmakuPosition(currentTime)
}

/**
 * 加载弹幕数据
 * @param {number} currentTime - 当前播放时间（秒）
 */
const loadDanmaku = async (currentTime) => {
  const start = Math.floor(currentTime)
  const end = start + 30

  // 1. 检查缓存数据
  const cached = getCachedDanmaku(start, end)
  if (cached.length > 0) {
    visibleDanmaku.value = [...visibleDanmaku.value, ...cached]
  }

  // 2. 获取新数据（模拟接口）
  const newDanmakuList = await mockFetchDanmaku(start, end)
  cacheDanmaku(newDanmakuList)
  visibleDanmaku.value = [...visibleDanmaku.value, ...newDanmakuList]

  // 新增：初始化弹幕动画属性
  newDanmakuList.forEach(d => {
    d.progress = Math.max((currentTime - d.playTime) / props.moveDuration, 0)
  })
  // 启动动画循环
  initDanmakuAnimation()

}

/**
 * 缓存弹幕数据
 * @param {Array} danmakuList - 待缓存的弹幕列表
 */
const cacheDanmaku = (danmakuList) => {
  if (!currentVideoId.value) return

  // 获取当前视频的缓存Map
  const videoCache = danmakuCache.get(currentVideoId.value) || new Map()
  danmakuList.forEach(danmaku => {
    const start = Math.floor(danmaku.playTime) // 按秒数分桶缓存
    const list = videoCache.get(start) || []
    videoCache.set(start, [...list, danmaku])
  })
  danmakuCache.set(currentVideoId.value, videoCache)
}

/**
 * 处理视频拖动事件
 * 清空当前弹幕并重新加载
 */
// const handleSeek = () => {
//   visibleDanmaku.value = []
//   // 取消当前动画帧
//   cancelAnimationFrame(animationFrame.value)
//
//   lastFetchTime.value = videoPlayer.value.currentTime
//   loadDanmaku(lastFetchTime.value)
// }
/**
 * 发送弹幕
 */
const sendDanmaku = () => {
  const danmakuData = {
    videoId: currentVideoId.value,
    userId: props.currentUser.id,
    content: newDanmaku.content,
    color: newDanmaku.color,
    size: newDanmaku.size,
    position: newDanmaku.position,
    playTime: videoPlayer.value.currentTime,
    likeCount: 0
  }
  // 模拟WebSocket发送
  ws.value.send(JSON.stringify(danmakuData))
  newDanmaku.content = ''
}

/**
 * 处理收到的新弹幕
 * @param {Object} danmaku - 弹幕数据
 */
const handleNewDanmaku = (danmaku) => {
  // 标记是否是自己发送的弹幕
  const processed = {
    ...danmaku,
    isMine: danmaku.userId === props.currentUser.id
  }

  const currentTime = videoPlayer.value.currentTime
  // 如果属于当前时间段则立即显示
  if (danmaku.playTime >= currentTime && danmaku.playTime <= currentTime + 30) {
    visibleDanmaku.value = [...visibleDanmaku.value, processed]
  }
  // 加入缓存
  cacheDanmaku([processed])
}



// ========== 工具方法 ========== //

/**
 * 生成弹幕样式
 * @param {Object} danmaku - 弹幕数据
 * @returns {Object} 样式对象
 */
// const getDanmakuStyle = (danmaku) => {
//   console.log(danmaku)
//   // 计算水平位移（从右到左）
//   const translateX = `${100 - danmaku.progress * 200}%` // 200%确保完全移出屏幕
//
//
//   return {
//     color: danmaku.color,
//     fontSize: `${danmaku.size}px`,
//     top: getPosition(danmaku.position),
//     transform: `translateX(${translateX})`,
//     transition: `all ${props.moveDuration}s linear` // 控制移动速度
//   }
// }
// 修改后的样式生成方法
// const getDanmakuStyle = (danmaku) => {
//   return {
//     color: danmaku.color,
//     fontSize: `${danmaku.size}px`,
//     top: getPosition(danmaku.position),
//     transform: `translateX(${-danmaku.translateX}px)`,
//     transition: `transform ${props.moveDuration}s linear`,
//     // 确保弹幕初始位置在容器右侧
//     left: `${canvasWidth.value}px`
//   }
// }


const getDanmakuStyle = (danmaku) => {
  return {
    color: danmaku.color,
    fontSize: `${danmaku.size}px`,
    top: getPosition(danmaku.position),
    // 添加动画延迟（根据弹幕出现时间计算）

    // 自定义属性传递动画时间
    '--move-duration': `${props.moveDuration}s`
  }
}
//  animationDelay: `${danmaku.playTime - videoPlayer.value.currentTime}s`,

// 弹幕移出后移除
const removeDanmaku = (danmaku) => {
  visibleDanmaku.value = visibleDanmaku.value.filter(d => d.id !== danmaku.id)
}

// 修改拖动处理
const handleSeek = () => {
  // 清除所有弹幕（立即终止动画）
  visibleDanmaku.value = []
  // 重新加载弹幕
  loadDanmaku(videoPlayer.value.currentTime)
}


/**
 * 获取弹幕垂直位置
 * @param {string} pos - 位置标识（top/center/bottom）
 * @returns {string} CSS定位值
 */
const getPosition = (pos) => {
  const positions = {
    top: '10%',    // 顶部留10%空间
    center: '50%', // 垂直居中
    bottom: '90%'  // 底部留10%空间
  }
  return positions[pos] || '10%'
}

// ========== 模拟数据方法 ========== //
/**
 * 模拟获取弹幕接口
 * @param {number} start - 起始时间（秒）
 * @param {number} end - 结束时间（秒）
 * @returns {Promise<Array>} 弹幕数组
 */
const mockFetchDanmaku = async (start, end) => {
  // 生成3条测试弹幕
  return [...Array(3)].map((_, i) => ({
    id: Date.now() + i,
    videoId: currentVideoId.value,
    userId: Math.random() > 0.5 ? props.currentUser.id : 999, // 随机用户
    content: `模拟弹幕${i}`,
    color: ['#ff0000', '#00ff00', '#0000ff'][i % 3], // 循环取色
    size: 24,
    position: ['top', 'center', 'bottom'][i % 3], // 循环位置
    playTime: start + Math.random() * (end - start), // 随机时间点
    likeCount: Math.floor(Math.random() * 10), // 随机点赞数
    isMine: false // 后续处理时会覆盖
  }))
}

/**
 * 处理视频播放结束事件
 */
const handleVideoEnd = () => {
  // 1. 检查是否有后续视频
  if (currentVideoIndex.value < props.videoList.length - 1) {
    // 切换到下一个视频
    currentVideoIndex.value++
  } else {
    // 循环播放设置（可根据需要添加循环配置项）
    currentVideoIndex.value = 0
  }

  // 2. 重置弹幕系统
  visibleDanmaku.value = []
  danmakuCache.delete(currentVideoId.value)

  // 3. 加载新视频的初始弹幕
  loadDanmaku(0)
}


/**
 * 从缓存获取指定时间范围的弹幕
 * @param {number} start - 起始时间(秒)
 * @param {number} end - 结束时间(秒)
 * @returns {Array} 弹幕数组
 */
const getCachedDanmaku = (start, end) => {
  if (!currentVideoId.value) return []

  // 1. 获取当前视频的缓存Map
  const videoCache = danmakuCache.get(currentVideoId.value) || new Map()

  // 2. 生成需要检查的时间段（按秒分桶）
  const cachedDanmaku = []
  for (let t = Math.floor(start); t <= Math.ceil(end); t++) {
    const bucket = videoCache.get(t) || []
    cachedDanmaku.push(...bucket)
  }

  // 3. 过滤精确时间范围
  return cachedDanmaku.filter(d =>
      d.playTime >= start &&
      d.playTime <= end
  )
}

// 修改视频结束逻辑
if (props.loop) {
  currentVideoIndex.value = currentVideoIndex.value < props.videoList.length - 1
      ? currentVideoIndex.value + 1
      : 0
}


// ========== 预留功能 ========== //
const handleLike = (danmaku) => {
  // TODO: 实现点赞逻辑
  console.log('点赞弹幕:', danmaku.id)
}
</script>

<style scoped>
@keyframes danmaku-move {
  0% {
    transform: translateX(800px); /* 从视窗右侧开始 */
  }
  100% {
    transform: translateX(-100%); /* 移动到元素自身宽度左外侧 */
  }
}



/* 样式保持不变 */
.danmaku-container {
  position: relative;
  width: 800px;
  height: 600px;
  margin: 0 auto;
}

.danmaku-canvas {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.danmaku-item {
  position: absolute;
  white-space: nowrap;
  will-change: transform;
  /* 添加初始位置过渡 */
  transition: transform linear;
  /* 确保弹幕从右侧进入 */
  transform: translateX(100%);
}

.content.mine {
  border: 2px solid yellow;
  padding: 2px;
}

.like-icon {
  margin-right: 5px;
}

.danmaku-control {
  margin-top: 20px;
}

.test-box{
  width: 100px;
  height: 60px;
  background-color: #6769ff;
  transition: all 5s linear;
}
.test-box:hover{
  transform: translateX(-200px);
}

.danmaku-item {
  position: absolute;
  white-space: nowrap;
  animation: danmaku-move var(--move-duration) linear forwards;
  animation-play-state: running; /* 确保动画始终运行 */
  will-change: transform;
}

/* 暂停已过期弹幕的动画 */
.danmaku-item.expired {
  animation-play-state: paused;
}
</style>